package com.ruicar.afs.cloud.basic.proceeds.pay.service.impl;

import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.common.entity.*;
import com.ruicar.afs.cloud.basic.common.service.*;
import com.ruicar.afs.cloud.basic.feign.CaseForChannelInfoFeign;
import com.ruicar.afs.cloud.basic.feign.ChannelInfoFeign;
import com.ruicar.afs.cloud.basic.feign.dto.ChannelAccountDto;
import com.ruicar.afs.cloud.basic.proceeds.pay.condition.PayListQueryCondition;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentBank;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentInterfaceLog;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentPool;
import com.ruicar.afs.cloud.basic.proceeds.pay.entity.BasicPaymentRecord;
import com.ruicar.afs.cloud.basic.proceeds.pay.mapper.BasicPaymentPoolMapper;
import com.ruicar.afs.cloud.basic.proceeds.pay.service.*;
import com.ruicar.afs.cloud.bizcommon.voucher.service.VoucherFlowService;
import com.ruicar.afs.cloud.common.config.ContractFeginConfig;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.afscorebusiness.enums.MessageParamEnum;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.modules.dto.mq.voucher.VoucherFlowInfoDto;
import com.ruicar.afs.cloud.common.modules.enums.BusinessType;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.easypass.enums.RsponseStatusEnum;
import com.ruicar.afs.cloud.easypass.process.dto.EasypassRsponseBean;
import com.ruicar.afs.cloud.easypass.process.dto.PayBatchApplyDTO;
import com.ruicar.afs.cloud.easypass.process.dto.PayBatchApplyDTO.PayBatchApplyListDTO;
import com.ruicar.afs.cloud.easypass.process.dto.PayResultQryDTO;
import com.ruicar.afs.cloud.easypass.process.service.IEasypassProcessService;
import com.ruicar.afs.cloud.message.sendmessage.config.MessageConfig;
import com.ruicar.afs.cloud.message.sendmessage.dto.MessageDataDto;
import com.ruicar.afs.cloud.message.sendmessage.dto.SendMessageDto;
import com.ruicar.afs.cloud.message.sendmessage.dto.SendResultInfoDto;
import com.ruicar.afs.cloud.message.sendmessage.service.MessageService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author: Lee
 * @date 2020-05-30 04:35:07
 * @description
 */
@Service
@AllArgsConstructor
@Slf4j
public class BasicPaymentPoolServiceImpl extends ServiceImpl<BasicPaymentPoolMapper, BasicPaymentPool>
		implements BasicPaymentPoolService {


	private final IEasypassProcessService easypassProcessService;

	private final UidGenerator uidGenerator;
	private final BasicPaymentRecordService basicPaymentRecordService;

	private final BasicPaymentInterfaceLogService basicPaymentInterfaceLogService;

	private final BasicPaymentWriteOffService basicPaymentWriteOffService;

	private final BasicPaymentOperateLogService basicPaymentOperateLogService;

	private final BasicMainInfoService basicMainInfoService;

	private final BasicPaymentPoolDetailsService basicPaymentPoolDetailsService;

	private final BasicAutoPaymentConfigService basicAutoPaymentConfigService;

	private final BasicPaymentBankService basicPaymentBankService;

	private final CaseForChannelInfoFeign caseForChannelInfoFeign;

	private final ChannelInfoFeign channelInfoFeign;

	private final ContractFeginConfig contractFeginConfig;

	private final BasicChannelInfoService basicChannelInfoService;

	private final VoucherFlowService voucherFlowService;

	private final BasicCarDetailsService basicCarDetailsService;

	private final BasicCustBaseInfoService basicCustBaseInfoService;

	private final BasicContractCustRelationService basicContractCustRelationService;

    private final MessageService messageService;
    private  final MessageConfig messageConfig;
	@Override
	public List<String> queryMsgIdList() {
		return baseMapper.queryMsgIdList();
	}

	@Override
	public IResponse queryPayMentByQueryParam(PayListQueryCondition payListQueryCondition) {
		Page page = new Page(payListQueryCondition.getPageNum(), payListQueryCondition.getPageSize());
		return IResponse.success(
				this.baseMapper.queryPayMentByQueryParam(page, payListQueryCondition));
	}
	@Override
	public IResponse exportPayList(PayListQueryCondition payListQueryCondition) {
		Page page = new Page(1, 100000000);
		return IResponse.success(
				this.baseMapper.queryPayMentByQueryParam(page, payListQueryCondition));
	}

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendPayOrder(BasicPaymentPool paymentPool, String chlCd) {
        /**  组装代付dto by ZC.GUO  **/
        List<PayBatchApplyListDTO> applyList = new ArrayList<>();
        PayBatchApplyDTO applyDto = new PayBatchApplyDTO();
        PayBatchApplyListDTO dto = this.buildDetail(paymentPool);
        dto.setChlCd(chlCd);
        applyList.add(dto);
        applyDto.setData(applyList);
        sendMessageToEasyPass(applyDto, paymentPool);
    }

    /**
     * 根据付款池数据组装付款明细报文
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    private PayBatchApplyListDTO buildDetail(BasicPaymentPool pool) {
        PayBatchApplyListDTO dto = new PayBatchApplyListDTO();
        dto.setSeqNo(String.valueOf(pool.getSeqNo()));
        dto.setContractNo(pool.getContractNo());
        dto.setPayAcctNo(pool.getPaymentAccount());

        /**  车架号和申请编号 by ZC.GUO  **/
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, pool.getContractNo())
        );
        if (EmptyUtils.isNotEmpty(mainInfo)) {
            dto.setApplicationNo(mainInfo.getApplyNo());
        }
        BasicCarDetails carDetails = basicCarDetailsService.getOne(Wrappers.<BasicCarDetails>query().lambda()
                .eq(BasicCarDetails::getContractNo, pool.getContractNo()), false);
        if (EmptyUtils.isNotEmpty(carDetails)) {
            dto.setFrameNumber(carDetails.getCarVin());
        }
        /**  备注字段取对应合同的客户姓名 by ZC.GUO  **/
        BasicContractCustRelation contractCustRelation = basicContractCustRelationService.getOne(Wrappers.<BasicContractCustRelation>query().lambda()
                .eq(BasicContractCustRelation::getContractNo, pool.getContractNo())
                .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON)
        );

        if (EmptyUtils.isNotEmpty(contractCustRelation)) {
            BasicCustBaseInfo custBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>query().lambda()
                    .eq(BasicCustBaseInfo::getCustNo, contractCustRelation.getCustNo())
            );
            if (EmptyUtils.isNotEmpty(custBaseInfo)) {
                dto.setRmk(custBaseInfo.getCustName());
            }
        }


        if (pool.getIsConglomerate() == YesOrNoEnum.yes) {
            dto.setIsFlag("3");
        } else {
            dto.setIsFlag("2");
        }
        dto.setRecAcctBkNm(pool.getReceiptBankName());
        dto.setRecAcctNo(pool.getReceiptAccount());
        dto.setRecAcctNm(pool.getReceiptAccountName());
        dto.setRecAcctBkNo(pool.getReceiptEbankCode());
        dto.setPayAmount(String.valueOf(pool.getPaymentAmt()));
        dto.setPayAcctNo(pool.getPaymentAccount());
        return dto;
    }


    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
    public void autoPay(List<BasicPaymentPool> poolList, String chlCd, BasicPaymentBank bankAccount) {
        String msgId = StringUtils.rightPad(String.valueOf(uidGenerator.getUID()), 32, "0");
        List<PayBatchApplyListDTO> applyList = new ArrayList<>();
        PayBatchApplyDTO applyDto = new PayBatchApplyDTO();
        int i = 1;
        if (EmptyUtils.isNotEmpty(poolList)){
            for (BasicPaymentPool pool : poolList){
                pool.setRevision(pool.getRevision() + 1);
                pool.setIsPaying(YesOrNoEnum.yes);
                pool.setMsgid(msgId);
                pool.setPaymentBankCode(bankAccount.getPaymentBankCode());
                pool.setPaymentAccount(bankAccount.getPaymentAccount());
                pool.setPaymentAccountName(bankAccount.getPaymentAccountName());
                pool.setPaymentMode(PaymentModeEnum.autoPayment);
                if (pool.getPaymentBankCode().equalsIgnoreCase(pool.getReceiptBankCode())){
                    pool.setIsConglomerate(YesOrNoEnum.no);
                }else{
                    pool.setIsConglomerate(YesOrNoEnum.yes);
                }
                pool.setSeqNo(i);
                i++;
                PayBatchApplyListDTO dto = this.buildDetail(pool);
                dto.setChlCd(chlCd);
                applyList.add(dto);
            }
            /**  信息先更新后发送 by ZC.GUO  **/
            this.updateBatchById(poolList);
            applyDto.setData(applyList);
            applyDto.setChlCd(chlCd);
            sendMessageToEasyPass(applyDto, poolList, msgId);
        }
    }

    @Override
    public boolean lockWhenStartPay(BasicPaymentPool basicPaymentPool) {
        int num = baseMapper.lockWhenStartPay(basicPaymentPool.getId(), basicPaymentPool.getRevision());
        if (num < 1) {
            log.warn("乐观锁生效，跳过放款操作，付款池id为：{}，乐观锁值为{}", basicPaymentPool.getId(), basicPaymentPool.getRevision());
            return false;
        }
        return true;
    }
    @Override
    public boolean readySingleWhenStartPay(BasicPaymentPool basicPaymentPool) {
        int num = baseMapper.readySingleWhenStartPay(basicPaymentPool.getId(), basicPaymentPool.getIsPaying());
        if (num < 1) {
            log.warn("锁定失败，付款池id为：{}", basicPaymentPool.getId());
            return false;
        }
        return true;
    }
    @Override
    public boolean readyBatchWhenStartPay(List<Long> idList) {
        List<Long> successIdList = new ArrayList<>();
        for (Long id : idList){
            int count = baseMapper.readySingleWhenStartPay(id,YesOrNoEnum.yes);
            if(count == 0) {
                log.info("付款池记录锁定失败，id:[{}]", new Object[]{id});
                break;
            }else{
                successIdList.add(id);
            }
        }
        if (successIdList.size() == idList.size()){
            return true;
        }else{
            for (Long id : successIdList){
                baseMapper.readySingleWhenStartPay(id,YesOrNoEnum.no);
            }
            return false;
        }
    }

    @Override
    public boolean updatePaymentPoolStatus(YesOrNoEnum action, List<Long> idList) {
        int count = baseMapper.updatePaymentPoolStatus(action,idList);
        if (count<idList.size()){
            return false;
        }else {
            return true;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void queryAndChangeAccountInfo(BasicPaymentPool paymentPool) {
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, paymentPool.getContractNo())
        );
        String business = BusinessTypeEnum.newCar.equals(mainInfo.getBusinessType()) ? "01" : "02";
        /**  查询案件服务接口获取最新账号 by ZC.GUO  **/
        Map<String, String> headers = new HashMap<>(2);
        headers.put("clientId", contractFeginConfig.getCaseClientId());
        headers.put("clientSecret", contractFeginConfig.getCaseClientSecret());
        headers.put("Content-Type", MediaType.APPLICATION_JSON_VALUE);
        IResponse<ChannelAccountDto> iResponse = caseForChannelInfoFeign.queryAccountInfo(mainInfo.getChannelId(), business, headers);
        if (CommonConstants.SUCCESS.equals(iResponse.getCode())) {
            /**  对比账号信息 by ZC.GUO  **/
            ChannelAccountDto channelAccountDto = iResponse.getData();
            if (EmptyUtils.isNotEmpty(channelAccountDto)) {
                boolean isChange = true;
                /**  账号、名称、联行号 by ZC.GUO  **/
                isChange = isChange && channelAccountDto.getReceivingAccount().equals(paymentPool.getReceiptAccount())
                        && channelAccountDto.getReceivingName().equals(paymentPool.getReceiptAccountName())
                        && channelAccountDto.getElectronicBankNo().equals(paymentPool.getReceiptEbankCode());
                /**  可以直接修改账号 by ZC.GUO  **/
                if (!isChange) {
                    /**  案件渠道信息修改 by ZC.GUO  **/
                    BasicChannelInfo channelInfo = basicChannelInfoService.getOne(Wrappers.<BasicChannelInfo>query().lambda()
                            .eq(BasicChannelInfo::getContractNo, paymentPool.getContractNo())
                    );
                    channelInfo.setReceivingAccount(channelAccountDto.getReceivingAccount());
                    channelInfo.setReceivingName(channelAccountDto.getReceivingName());
                    channelInfo.setReceivingBank(channelAccountDto.getReceivingBank());
                    channelInfo.setReceivingSubBranch(channelAccountDto.getReceivingSubBranch());
                    channelInfo.setElectronicBankNo(channelAccountDto.getElectronicBankNo());
                    channelInfo.setOpeningBankProvince(channelAccountDto.getOpeningBankProvince());
                    channelInfo.setOpeningBankCity(channelAccountDto.getOpeningBankCity());
                    basicChannelInfoService.updateById(channelInfo);
                    /**  付款池数据账号修改 by ZC.GUO  **/
                    this.changeReceiptAccountInfo(channelInfo, paymentPool);

                }
            }
        }else{
            throw new AfsBaseException(iResponse.getMsg());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sendMsgAndUpdatePool(BasicPaymentPool paymentPool) {
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, paymentPool.getContractNo())
        );
        BasicChannelInfo channelInfo = basicChannelInfoService.getOne(Wrappers.<BasicChannelInfo>query().lambda()
                .eq(BasicChannelInfo::getContractNo, paymentPool.getContractNo())
        );
        String content = channelInfo.getChannelFullName()+"合同："+mainInfo.getContractNo()+"在放款时未成功，银行卡号：" + paymentPool.getReceiptAccount() + "，不正确或者异常，请联系合作商解决。";

        /**  查询案件服务接口获取最新账号 by ZC.GUO  **/
        Map<String, String> headers = new HashMap<>(2);

        headers.put("clientId", contractFeginConfig.getChannelClientId());
        headers.put("clientSecret", contractFeginConfig.getChannelClientSecret());
        IResponse<String> iResponse = channelInfoFeign.sendMsgToUpdatePool(mainInfo.getChannelId(), content, headers);
        if (!CommonConstants.SUCCESS.equals(iResponse.getCode())) {
            throw new AfsBaseException(iResponse.getMsg());
        }else{
            /**  发送信息成功，更新状态 by ZC.GUO  **/
            paymentPool.setAccountChangeStatus(AccountStatusEnum.send);
            this.updateById(paymentPool);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void handleExceptionForPayment(List<Long> idList) {
        if (EmptyUtils.isNotEmpty(idList)){
            for (Long id :idList){
                BasicPaymentPool paymentPool = this.getById(id);
                if (EmptyUtils.isNotEmpty(paymentPool)){
                    if (EmptyUtils.isEmpty(paymentPool.getAccountChangeStatus()) || AccountStatusEnum.change.equals(paymentPool.getAccountChangeStatus())){

                        /**  已经变更为最新的账号或者还没发送修改消息，发送修改消息，并且同一收款账号的未付款和待付款的付款记录同步更新状态为已发送修改消息 by ZC.GUO  **/
                        this.sendMsgAndUpdatePool(paymentPool);
                    }else{
                        /**  已经发送过了修改消息，直接去查最新的账号信息并做更新 by ZC.GUO  **/
                        this.queryAndChangeAccountInfo(paymentPool);
                    }

                }
            }
        }

    }

    @Override
    public void changeReceiptAccountInfo(BasicChannelInfo channelInfo, BasicPaymentPool paymentPool) {
        /**  付款池信息 by ZC.GUO  **/
        paymentPool.setReceiptBankCode(channelInfo.getReceivingBank());
        paymentPool.setReceiptBankName(channelInfo.getReceivingSubBranch());
        paymentPool.setReceiptAccount(channelInfo.getReceivingAccount());
        paymentPool.setReceiptAccountName(channelInfo.getReceivingName());
        paymentPool.setReceiptEbankCode(channelInfo.getElectronicBankNo());
        paymentPool.setAccountChangeStatus(AccountStatusEnum.change);
        this.updateById(paymentPool);
        /**  付款池明细信息 by ZC.GUO  **/
        basicPaymentPoolDetailsService.changeAccount(paymentPool);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
    public void sendPaymentPool(BasicPaymentPool pool,String chlCd,BasicPaymentBank payAccount) {

        pool.setPaymentBankCode(payAccount.getPaymentBankCode());
        pool.setPaymentAccount(payAccount.getPaymentAccount());
        pool.setPaymentAccountName(payAccount.getPaymentAccountName());
        pool.setPaymentMode(PaymentModeEnum.manualPayment);

        if (pool.getPaymentBankCode().equalsIgnoreCase(pool.getReceiptBankCode())){
            pool.setIsConglomerate(YesOrNoEnum.no);
        }else{
            pool.setIsConglomerate(YesOrNoEnum.yes);
        }
        pool.setRevision(pool.getRevision() + 1);
        pool.setIsPaying(YesOrNoEnum.yes);

        String msgid = StringUtils.rightPad(String.valueOf(uidGenerator.getUID()), 32, "0");
        pool.setMsgid(msgid);
        pool.setSeqNo(1);

        /**  信息先更新后发送 by ZC.GUO  **/
        this.updateById(pool);

        this.sendPayOrder(pool, chlCd);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void queryPayResult(String msgid) {
        EasypassRsponseBean<PayResultQryDTO> easypassRsponseBean = easypassProcessService.payResultQry(msgid);
        if (AfsEnumUtil.key(RsponseStatusEnum.HEAD_SUCCESS).equals(easypassRsponseBean.getResultCode())) {
            /**  付款结果处理 by ZC.GUO  **/
            this.handlePayResult(easypassRsponseBean.getBody(), msgid);
        }//msgid 数据不存在
        else if (AfsEnumUtil.key(RsponseStatusEnum.HEAD_REPEAT).equals(easypassRsponseBean.getResultCode())) {
            /**  只对付款中的付款记录进行处理 by ZC.GUO  **/
            List<BasicPaymentPool> paymentPools = this.list(Wrappers.<BasicPaymentPool>query().lambda()
                    .eq(BasicPaymentPool::getMsgid, msgid)
                    .eq(BasicPaymentPool::getPaymentStatus, PaymentStatusEnum.paying));
            for (BasicPaymentPool paymentPool : paymentPools) {
                this.payFail(paymentPool, easypassRsponseBean.getResultDesc());
            }

        }
    }

    @Override
    public void handlePayResult(BasicPaymentPool paymentPool, PayResultQryDTO.PayResultQryListDTO resultDetail) {
        /**  付款成功 by ZC.GUO  **/
        if (AfsEnumUtil.key(RsponseStatusEnum.SUCCESS).equals(resultDetail.getStatus())) {
            this.paySuccess(paymentPool, resultDetail.getMessage());
        }
        /**  付款失败 by ZC.GUO  **/
        else if (AfsEnumUtil.key(RsponseStatusEnum.FAIL).equals(resultDetail.getStatus())) {
            this.payFail(paymentPool, resultDetail.getMessage());
        }
        /**  暂无付款结果 by ZC.GUO  **/
        else if (AfsEnumUtil.key(RsponseStatusEnum.EXECING).equals(resultDetail.getStatus())) {
            this.paying(paymentPool, resultDetail.getMessage());
        }
    }

    @Override
    public void handlePayResult(PayResultQryDTO payResultQryDTO, String msgid) {
        List<PayResultQryDTO.PayResultQryListDTO> resultDetailList = payResultQryDTO.getStatus();
        if (EmptyUtils.isNotEmpty(resultDetailList)) {
            for (PayResultQryDTO.PayResultQryListDTO resultDetail : resultDetailList) {
                BasicPaymentPool paymentPool = this.getOne(Wrappers.<BasicPaymentPool>query().lambda()
                        .eq(BasicPaymentPool::getMsgid, msgid)
                        .eq(BasicPaymentPool::getSeqNo, resultDetail.getSeqNo())
                        /**  只对付款中的付款记录进行处理 by ZC.GUO  **/
                        .eq(BasicPaymentPool::getPaymentStatus, PaymentStatusEnum.paying)
                );
                if (EmptyUtils.isNotEmpty(paymentPool)) {
                    this.handlePayResult(paymentPool, resultDetail);
                }
            }
        }
    }

    @Override
    public void paySuccess(BasicPaymentPool paymentPool, String msg) {
        /**  付款池数据更新 by ZC.GUO  **/
        paymentPool.setActivationTime(Calendar.getInstance().getTime());
        paymentPool.setPaymentStatus(PaymentStatusEnum.successPayment);
        paymentPool.setLastResultTime(Calendar.getInstance().getTime());
        this.updateById(paymentPool);
        /**  付款池明细数据 by ZC.GUO  **/
        basicPaymentPoolDetailsService.paySuccess(paymentPool);
        /**  付款记录更新 by ZC.GUO  **/
        BasicPaymentRecord paymentRecord = basicPaymentRecordService.getOne(Wrappers.<BasicPaymentRecord>query().lambda()
                .eq(BasicPaymentRecord::getPoolId, paymentPool.getId())
                .in(BasicPaymentRecord::getStatus, PaymentRecordEnum.successSend,PaymentRecordEnum.queryResultSuccess)
                .eq(BasicPaymentRecord::getPaymentResult, PaymentStatusEnum.paying)
        );
        if (EmptyUtils.isEmpty(paymentRecord)) {
            paymentRecord = basicPaymentRecordService.addPaymentRecord(paymentPool, PaymentRecordEnum.successSend,PaymentStatusEnum.successPayment);
        }
        paymentRecord.setStatus(PaymentRecordEnum.queryResultSuccess);
        paymentRecord.setPaymentResult(PaymentStatusEnum.successPayment);
        paymentRecord.setCallBackTime(Calendar.getInstance().getTime());
        paymentRecord.setCallBackMsg(msg);
        paymentRecord.setRemarks(null);
        basicPaymentRecordService.updateById(paymentRecord);
        /**  付款核销数据新增 by ZC.GUO  **/
        basicPaymentWriteOffService.addPaymentWriteOff(paymentRecord, paymentPool);
        /**  main表数据更新 by ZC.GUO  **/
        BasicMainInfo mainInfo = basicMainInfoService.getOne(Wrappers.<BasicMainInfo>query().lambda()
                .eq(BasicMainInfo::getContractNo, paymentPool.getContractNo())
        );
        if (EmptyUtils.isNotEmpty(mainInfo)) {
            mainInfo.setLoanDate(Calendar.getInstance().getTime());
            basicMainInfoService.updateById(mainInfo);
        }

        VoucherFlowInfoDto voucherFlowInfoDto = new VoucherFlowInfoDto();
        voucherFlowInfoDto.setBuriedPointNo(VoucherBuriedPointNo.contractLoan);
        voucherFlowInfoDto.setContractNo(mainInfo.getContractNo());
        voucherFlowInfoDto.setKeepAccountDate(mainInfo.getLoanDate());
        voucherFlowInfoDto.setTransNo(paymentPool.getId().toString());
        voucherFlowInfoDto.setBusinessType((BusinessType) AfsEnumUtil
                .getEnum(AfsEnumUtil.key(mainInfo.getBusinessType()), BusinessType.class));
        voucherFlowInfoDto.setFinancialProducts(mainInfo.getProductName());
        voucherFlowInfoDto.setDealerName(mainInfo.getChannelFullName());
        log.info("合同号:{}，埋点号:{}，合同付款成功===开始保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());
        voucherFlowService.sendFlow(voucherFlowInfoDto);
        log.info("合同号:{}，埋点号:{}，合同付款成功===结束保存流水", voucherFlowInfoDto.getBuriedPointNo(), voucherFlowInfoDto.getContractNo());
        /**  发送付款成功短信 by ZC.GUO  **/
        this.sendPaySuccessMsg(paymentPool,mainInfo);

    }

    @Override
    public void sendPaySuccessMsg(BasicPaymentPool paymentPool, BasicMainInfo mainInfo) {
        try{
            BasicChannelInfo channelInfo = basicChannelInfoService.getOne(Wrappers.<BasicChannelInfo>query().lambda()
                    .eq(BasicChannelInfo::getContractNo, paymentPool.getContractNo())
            );
            BasicContractCustRelation mainBasicContractCustRelation = basicContractCustRelationService.getOne(Wrappers.<BasicContractCustRelation>query().lambda()
                    .eq(BasicContractCustRelation::getContractNo, paymentPool.getContractNo())
                    .eq(BasicContractCustRelation::getCustRole, PersonRoleTypeEnum.MAIN_PERSON));
            BasicCustBaseInfo mainCustBaseInfo = null;
            if (mainBasicContractCustRelation != null) {
                mainCustBaseInfo = basicCustBaseInfoService.getOne(Wrappers.<BasicCustBaseInfo>query().lambda()
                        .eq(BasicCustBaseInfo::getCustNo, mainBasicContractCustRelation.getCustNo())
                );
            }
            if (EmptyUtils.isNotEmpty(channelInfo)&&EmptyUtils.isNotEmpty(channelInfo.getContactPhone())&&EmptyUtils.isNotEmpty(mainCustBaseInfo)){
                List<MessageDataDto>  messageDataDto = new ArrayList<>();
                MessageDataDto dataDto = new MessageDataDto();
                dataDto.setDeptId(MessageParamEnum.DEPTID.getCode());
                dataDto.setOrigin(MessageParamEnum.ORIGIN.getCode());
                dataDto.setPhone(channelInfo.getContactPhone());
                /**  防重复-不防重复，有多少发多少 by ZC.GUO  **/
                dataDto.setSummaryId(channelInfo.getContactPhone() + String.valueOf(Calendar.getInstance().getTime().getTime())+ UUID.randomUUID().toString());
                String content = "尊敬的经销商：我公司已完成贷.款申请书编号"+mainInfo.getApplyNo()+"客户"+mainCustBaseInfo.getCustName()+"的贷.款拨付，请查收。同时提醒您，在放款后请根据文档归档清单的要求及时寄送相应材料至我司，以免影响您的提前放款业务，感谢您的支持。";
                dataDto.setSmsContent(content);
                dataDto.setTemplateId("W407");
                dataDto.setPriority("1");
                messageDataDto.add(dataDto);
                SendMessageDto messageDto= new SendMessageDto();
                messageDto.setChannel("1");
                messageDto.setCode(MessageParamEnum.CODE.getCode());
                messageDto.setTimestamp(System.currentTimeMillis()/1000+"");
                messageDto.setUid(MessageParamEnum.UID.getCode());
                messageDto.setMessageDataDto(messageDataDto);
                SendResultInfoDto sendResultInfoDto = messageService.sendMessageData(messageDto);
                if ("false".equals(sendResultInfoDto.getResult())) {
                    log.error("合同号：{}付款成功，提示短信发送失败，请注意补发");
                }
            }else{
                log.error("合同号：{}付款成功，提示短信发送失败，请注意补发");
            }
        }catch (Exception e){
            log.error("合同号：{}付款成功，提示短信发送失败，请注意补发");
        }

    }


    @Override
    public void payFail(BasicPaymentPool paymentPool, String msg) {
        /**  付款池数据更新 by ZC.GUO  **/
        paymentPool.setPaymentStatus(PaymentStatusEnum.failPayment);
        paymentPool.setLastResultTime(Calendar.getInstance().getTime());
        paymentPool.setLastFailReason(msg);
        paymentPool.setIsPaying(YesOrNoEnum.no);
        paymentPool.setMsgid(null);
        this.updateById(paymentPool);
        /**  付款记录更新 by ZC.GUO  **/
        BasicPaymentRecord paymentRecord = basicPaymentRecordService.getOne(Wrappers.<BasicPaymentRecord>query().lambda()
                .eq(BasicPaymentRecord::getPoolId, paymentPool.getId())
                .in(BasicPaymentRecord::getStatus, PaymentRecordEnum.successSend,PaymentRecordEnum.queryResultSuccess)
                .eq(BasicPaymentRecord::getPaymentResult, PaymentStatusEnum.paying)
        );
        if (EmptyUtils.isEmpty(paymentRecord)) {
            paymentRecord = basicPaymentRecordService.addPaymentRecord(paymentPool, PaymentRecordEnum.queryResultSuccess,PaymentStatusEnum.failPayment);
        }
        paymentRecord.setStatus(PaymentRecordEnum.queryResultSuccess);
        paymentRecord.setPaymentResult(PaymentStatusEnum.failPayment);
        paymentRecord.setCallBackTime(Calendar.getInstance().getTime());
        paymentRecord.setCallBackMsg(msg);
        paymentRecord.setRemarks(null);
        basicPaymentRecordService.updateById(paymentRecord);
    }

    @Override
    public void paying(BasicPaymentPool paymentPool, String msg) {
        /**  付款记录更新 by ZC.GUO  **/
        BasicPaymentRecord paymentRecord = basicPaymentRecordService.getOne(Wrappers.<BasicPaymentRecord>query().lambda()
                .eq(BasicPaymentRecord::getPoolId, paymentPool.getId())
                .in(BasicPaymentRecord::getStatus, PaymentRecordEnum.successSend,PaymentRecordEnum.queryResultSuccess)
                .eq(BasicPaymentRecord::getPaymentResult, PaymentStatusEnum.paying)
        );
        if (EmptyUtils.isEmpty(paymentRecord)) {
            paymentRecord = basicPaymentRecordService.addPaymentRecord(paymentPool, PaymentRecordEnum.queryResultSuccess,PaymentStatusEnum.paying);
        }
        paymentRecord.setStatus(PaymentRecordEnum.queryResultSuccess);
        paymentRecord.setPaymentResult(PaymentStatusEnum.paying);
        paymentRecord.setCallBackTime(Calendar.getInstance().getTime());
        paymentRecord.setCallBackMsg(msg);
        paymentRecord.setRemarks(null);
        basicPaymentRecordService.updateById(paymentRecord);
    }

	/**
	 * 发送成功处理
	 *
	 * @param
	 * @return
	 * @author ZC.GUO
	 */
	private void sendSuccess(BasicPaymentPool paymentPool, EasypassRsponseBean bean, Date sendTime) {
        /**  解锁 by ZC.GUO  **/
        paymentPool.setIsPaying(YesOrNoEnum.no);
        paymentPool.setRevision(paymentPool.getRevision() + 1);
        paymentPool.setPaymentStatus(PaymentStatusEnum.paying);
        paymentPool.setSendTime(Calendar.getInstance().getTime());
        this.updateById(paymentPool);
        /**  付款记录 by ZC.GUO  **/
        BasicPaymentRecord paymentRecord = basicPaymentRecordService.addPaymentRecord(paymentPool, PaymentRecordEnum.successSend,PaymentStatusEnum.paying);
        /**  付款池操作记录 by ZC.GUO  **/
        basicPaymentOperateLogService.addOperateLog(paymentPool, OperateTypeEnum.manualPayment, OperateResultEnum.operateSuccess);
        /**  付款接口记录 by ZC.GUO  **/
        BasicPaymentInterfaceLog paymentInterfaceLog = new BasicPaymentInterfaceLog();
        paymentInterfaceLog.setRequestTime(sendTime);
        paymentInterfaceLog.setRecordId(paymentRecord.getId());
        paymentInterfaceLog.setInterfaceType(InterfaceTypeEnum.client);
        paymentInterfaceLog.setInterfaceCode(InterfaceCodeEnum.batchPayRequest);
        paymentInterfaceLog.setInterfaceName("代付申请_批量");
        paymentInterfaceLog.setResponseTime(Calendar.getInstance().getTime());
        paymentInterfaceLog.setRequestResult(RequestResultEnum.sendSuccess);
        paymentInterfaceLog.setResponseResult(ResponseResultEnum.responeSuccess);
        basicPaymentInterfaceLogService.save(paymentInterfaceLog);
	}

	/**
	 * 发送失败处理
	 *
	 * @param
	 * @return
	 * @author ZC.GUO
	 */
	private void sendFail(BasicPaymentPool paymentPool, EasypassRsponseBean bean, Date sendTime) {
		/**  解锁 by ZC.GUO  **/
		paymentPool.setIsPaying(YesOrNoEnum.no);
		paymentPool.setRevision(paymentPool.getRevision() + 1);
		paymentPool.setMsgid(null);
		this.updateById(paymentPool);
		/**  付款记录 by ZC.GUO  **/
		BasicPaymentRecord paymentRecord = basicPaymentRecordService.addPaymentRecord(paymentPool, PaymentRecordEnum.failSend,PaymentStatusEnum.failPayment);
		/**  付款池操作记录 by ZC.GUO  **/
		basicPaymentOperateLogService.addOperateLog(paymentPool, OperateTypeEnum.manualPayment, OperateResultEnum.operateFail);
		/**  付款接口记录 by ZC.GUO  **/
		BasicPaymentInterfaceLog paymentInterfaceLog = new BasicPaymentInterfaceLog();
		paymentInterfaceLog.setRequestTime(sendTime);
		paymentInterfaceLog.setRecordId(paymentRecord.getId());
		paymentInterfaceLog.setInterfaceType(InterfaceTypeEnum.client);
		paymentInterfaceLog.setInterfaceCode(InterfaceCodeEnum.batchPayRequest);
		paymentInterfaceLog.setInterfaceName("代付申请_批量");
		paymentInterfaceLog.setResponseTime(Calendar.getInstance().getTime());
		paymentInterfaceLog.setRequestResult(RequestResultEnum.sendSuccess);
		paymentInterfaceLog.setResponseResult(ResponseResultEnum.responeException);
		basicPaymentInterfaceLogService.save(paymentInterfaceLog);
		log.warn("发送睿易通出错:{},poolid:{}", bean.getResultDesc(), paymentPool.getId());
	}

	/**
	 * 批量付款发送动作
	 *
	 * @param
	 * @return
	 * @author ZC.GUO
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
	public void sendMessageToEasyPass(PayBatchApplyDTO dto, List<BasicPaymentPool> paymentPoolList, String msgid) {
		Date sendTime = Calendar.getInstance().getTime();
		EasypassRsponseBean bean = easypassProcessService.payBatchApply(dto, msgid);
		if (AfsEnumUtil.key(RsponseStatusEnum.HEAD_SUCCESS).equalsIgnoreCase(bean.getResultCode())) {
			for (BasicPaymentPool paymentPool : paymentPoolList) {
				this.sendSuccess(paymentPool, bean, sendTime);
                log.info("合同号{}付款发送成功", paymentPool.getContractNo());
			}
		}  else {
			for (BasicPaymentPool paymentPool : paymentPoolList) {
				this.sendFail(paymentPool, bean, sendTime);
                log.error("合同号{}付款发送失败，失败信息为：{}", paymentPool.getContractNo(),bean.getResultDesc());
			}
		}
	}

	/**
	 * 单笔付款发送动作
	 *
	 * @param
	 * @return
	 * @author ZC.GUO
	 */
	@Transactional(propagation = Propagation.REQUIRES_NEW, noRollbackFor = Exception.class)
	public void sendMessageToEasyPass(PayBatchApplyDTO dto, BasicPaymentPool paymentPool) {
		Date sendTime = Calendar.getInstance().getTime();
		EasypassRsponseBean bean = easypassProcessService.payBatchApply(dto, paymentPool.getMsgid());
		if (AfsEnumUtil.key(RsponseStatusEnum.HEAD_SUCCESS).equalsIgnoreCase(bean.getResultCode())) {
			this.sendSuccess(paymentPool, bean, sendTime);
			log.info("合同号{}付款发送成功", paymentPool.getContractNo());
		}
		else  {
			this.sendFail(paymentPool, bean, sendTime);
            log.error("合同号{}付款发送失败，失败信息为：{}", paymentPool.getContractNo(),bean.getResultDesc());
		}
	}
}
